Andrew McMillan: Storing Secrets
Something that has been annoying me recently with my bank has been that their website tells me that they will never ask for my password over the phone. And then their call centre asks me for my password. Over the phone. Of course the call centre doesn't mean my website password - they mean the special 'ultra-secure 5ekr1t code phrase', but they don't have a good, universally understood word to use for that. Hopefully they'll work one out, but they appear to have got the message anyway.
This got me to thinking about how these phrases are used, and how insecure they are in reality. After all when I store a website password I go to significant lengths to ensure that the same password is not represented by the same string of characters in my database. How vulnerable are our secrets in the databases of organisations we do business with?
<!--break--> Simple Password Storage Surprisingly often people do store passwords in databases in plain text, so that should their website get hacked someone would quite possibly be able to download the whole password database. Please feel free to name and shame these organisations in the comments below. My own pet hate in this regard is the 'Mailman' mailing list software: by default on 'mailman day' - the first day of each month - it sends me my password. In plain text. Of course many developers recognise this flaw, and work around it by using a one-way hash to obscure the password. Usually they choose md5 for their hashing algorithm though, and they often fail to use a 'salt' to randomise the plaintext prior to hashing. This means that even though a password might seem obscure like 'Supercalifragilisticexpialidocious!', and no doubt it will hash to something that seems obscure like 'a7290d426b6a1764af6fd7fba5db214e', but you can often find it straighforwardly by looking it up through one of the friendly reverse hash lookup websites. There's even a Digest::MD5::Reverse perl module on CPAN to interface to a bunch of these in a more automated way! Oh dear. One way to go beyond this is using a 1-way hashing algorithm, with a random salt included into the plaintext before the hashing, so that if (god forbid) two users had 'password' for their password I might see two rows in my database like:
<!--break--> Simple Password Storage Surprisingly often people do store passwords in databases in plain text, so that should their website get hacked someone would quite possibly be able to download the whole password database. Please feel free to name and shame these organisations in the comments below. My own pet hate in this regard is the 'Mailman' mailing list software: by default on 'mailman day' - the first day of each month - it sends me my password. In plain text. Of course many developers recognise this flaw, and work around it by using a one-way hash to obscure the password. Usually they choose md5 for their hashing algorithm though, and they often fail to use a 'salt' to randomise the plaintext prior to hashing. This means that even though a password might seem obscure like 'Supercalifragilisticexpialidocious!', and no doubt it will hash to something that seems obscure like 'a7290d426b6a1764af6fd7fba5db214e', but you can often find it straighforwardly by looking it up through one of the friendly reverse hash lookup websites. There's even a Digest::MD5::Reverse perl module on CPAN to interface to a bunch of these in a more automated way! Oh dear. One way to go beyond this is using a 1-way hashing algorithm, with a random salt included into the plaintext before the hashing, so that if (god forbid) two users had 'password' for their password I might see two rows in my database like:
davical=# select username, password from usr; username password -------------+------------------------------------------------ user1 SSHA qCctCH5dirYCf29uxJiE68LvmLRDdnBkbldiWlE= user2 SSHA y8yOzjoh9fSkVwLaXGoVtWdiIYxmU2FCb2dOZXc= (2 rows)When the user wants to log in I apply the same transformation to their incoming password (appending the same salt) and compare against my stored hash. If they match then it must be the same password they used previously. Storing passwords in this way secures them from casual, or even reasonably determined access, although naturally they can still be logged at the beginning and end of the communication - or even in the middle, if we didn't encrypt that bit! The PHP function I use to salt and hash the password is as follows:
/** * Make a salted SHA1 string, given a string and (possibly) a salt. PHP5 only (although it * could be made to work on PHP4 (@see http://www.openldap.org/faq/data/cache/347.html). The * algorithm used here is compatible with OpenLDAP so passwords generated through this * function should be able to be migrated to OpenLDAP. * * If no salt is supplied we will generate a random one. * * @param string $instr The string to be salted and SHA1'd * @param string $salt Some salt to sprinkle into the string to be SHA1'd so we don't * get the same PW always hashing to the same value. * @return string SSHA followed by a base64 encoded SHA1 of the salted string. */ function session_salted_sha1( $instr, $salt = "" ) if ( $salt == "" ) $salt = substr( base64_encode(sha1(rand(100000,9999999),true))), 2, 9); return ( sprintf(" SSHA %s", base64_encode(sha1($instr.$salt, true) . $salt)));What about Secret Code Phrases? The problem with these secret code phrases, apart from all of the forgetability and guessability problems that have repeatedly been identified elsewhere, is that they are much less likely to be stored in a one-way hash. Are you going to ask your call-centre staff to type in the customer's secret code phrase? Didn't think so. And if you did it's going to add pronouncability issues to the whole mix. So this means that those organisations who have our secret code phrases in their database will, in all likelihood, have them stored directly as plain text, displaying them to the random call-centre staffer along with all of our other account details, and especially making them vulnerable to accidental disclosure. Disclosure of a sort that doesn't necessarily involve knowing they have been disclosed. Proliferation of Use These things provide the appearance of security - 'Security Theatre' as Bruce Schneier terms it - and because of that they're taken up in a kind of a cargo cult of security: "if the banks do it that way it must be a really good form of security". This makes the problem much worse, because now I have to remember a secret code phrases not only for banks, but for ISPs, phone companies, online auction websites, and so on. How many mother's maiden names, favourite teachers and friend's phone numbers do I have? I'm sure I'm at well up whatever curve it is that measures the number of passwords a person has, because five years ago I had so many I started to store them all in an encrypted database - protected by a yet another password, of course. Now in order to get my story straight I have to store my 'secret code phrases' in there too. If I didn't store my secret code phrases in that database, I'd obviously be re-using them everywhere, from a very small set - perhaps the same one that everyone around me overhears, every time I have to ring my bank to authorise another payment from my account. Because the proliferation of use is not just the breadth of wannabe thespians hoping to climb on the stage of this latest play, but the way they want to use it all the time, too. In fact the only conversation I've had recently with my bank where they didn't want it was when they rang me. Obviously I was the only person who could answer a phone in my house, right? It isn't just security theatre: I think we can see that this analogy belongs much deeper into the sub-genre of 'Security Farce'. Is there a solution? I don't have any easy answers - other than the ones to my security questions, of course - but some improvements are possible. Other banks have quizzed me about stuff like recent expenditure or credit card limits from time to time, but I've usually passed those tests by reading my last bank statement - or failed them by not having it to hand! I don't really think that the answers can lie in that direction because the information is only quite loosely tied to my identity. For some parts of the call-centre handling of secret code phrases there are changes that could make them more secure, but in the fairly short term these organisations need to find a different way to perform these out of band identity checks. For the actual storage of the code phrases it would be a marginal improvement if the database did not contain the actual phrase. Perhaps it could be encrypted with some application-known key, so that it can be unencrypted when it needs to be displayed, but never stored in the clear. Of course there's still the problem with that key... Verification of the secret code phrase could be done by someone not involved in the transaction, so that the call could be temporarily passed into a 'verification stream' where a different person performed the verification step without the context of the account details or enquiry. Though this sort of complexity seems unlikely with call centres seemingly being outsourced to the cheapest supplier. One thing does seem likely to become increasingly true: there is less and less private data in our lives, and every time we share one of these little nuggets with our bank, or our electricity company, or our on-line associates-we-call-friends, is one more chance that it escapes into the hands of the foaming-at-the-mouth-terrorist-cracker-communist-nazi-right-wing-religious-fruitcake hordes. The highest bar for personal verification which any of my banks currently sets for me is a random choice from a set of personally entered questions, with a set of personally entered answers, for which I have to enter two randomly selected characters using my mouse. That's not bad for safe verification, and I'd have to be really impressed with their security if that was stored in the database by a passphrase-protected encryption key. With that bank I don't know what they do over the phone - I assume they've concluded they can trust my logged on persona enough that I can do what I want online, consequently I haven't had to call them and share those secrets with everyone in earshot. Maybe paranoid freaks like me will go back to a chequebook and close down on-line access to their bank accounts entirely when they find themselves having to supply a skin scraping in order to authorise their next $500 payment. "Please insert your finger in the AccuYou(tm) BloodSucker(tm) to proceed with this payment" - well, I guess it might cut down my spending! In any case, biometrics need to be understood before they can be used effectively and appropriately - and remotely over the phone is probably not one of the ways that they can be trusted to work.